package org.springblade.modules.resource.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iflytek.sc.ssp.uc.client.constant.UCConstant;
import com.iflytek.sc.ssp.uc.client.context.UCCasServiceContext;
import com.iflytek.sc.ssp.uc.client.service.UCService;
import com.iflytek.sc.ssp.uc.client.util.SignUtil;
import io.netty.util.internal.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenGranterBuilder;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.enterprise.entity.CompanyBasicInf;
import org.springblade.modules.enterprise.service.ICompanyBasicInfService;
import org.springblade.modules.resource.entity.*;
import org.springblade.modules.resource.service.IEsmsUserService;
import org.springblade.modules.resource.service.ILocalAttachService;
import org.springblade.modules.resource.service.ILocalOptionService;
import org.springblade.modules.resource.utils.FileUploadUtils;
import org.springblade.modules.resource.utils.HttpUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserDept;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.IUserDeptService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Slf4j
@Api(tags = {"公共接口"})
@RestController
@RequestMapping("/api/Common")
public class UcLoginController {


	private static String appSercert;

	@Resource
	private IEsmsUserService esmsUserService;
	@Resource
	private IUserService userService;
	@Resource
	private IUserDeptService userDeptService;

	@Resource
	private ICompanyBasicInfService companyBasicInfService;

	@Value("${uc-config.userInfoUrl}")
	private String userInfoUrl;

	@Value("${uc-config.legalSubUrl}")
	private String legalSubUrl;

	@Resource
	private ILocalOptionService localOptionService;
	@Resource
	private ILocalAttachService localAttachService;

	@Value("${blade.file.upload-path}")
	private String uploadPath;

	@Value("${blade.file.upload-domain}")
	private String uploadDomain;

	@Value("${blade.file.upload-prefix}")
	private String uploadPrefix;


	/**
	 * 上传文件并保存至本地附件表（跳过权限上传）
	 *
	 * @param file 文件
	 * @return ObjectStat
	 */
	@SneakyThrows
	@PostMapping("/upload-file")
	public R putFileAttach(@RequestParam MultipartFile file) {
		//文件原名
		String originalFileName = file.getOriginalFilename();
		//文件大小（kb）
		long size = file.getSize() / 1024;
		//获取上传目的文件夹路径
		LocalOption defaultOption = localOptionService.getDefaultOption();
		//拼接最终路径
		String finalPath = uploadPath + "/upload" + defaultOption.getUploadPath();
		//執行上傳操作返回鏈接
		String uploadFileUrl = FileUploadUtils.upload(finalPath, file);
		uploadFileUrl = uploadFileUrl.replace(uploadPath, uploadPrefix);
		//上傳后的名稱
		String fileName = uploadFileUrl.substring(uploadFileUrl.lastIndexOf("/") + 1);

		LocalAttach attach = new LocalAttach();
		String fileExtension = FileUtil.getFileExtension(fileName);
		attach.setAttachSize(size);
		attach.setExtension(fileExtension);
		attach.setName(fileName);
		attach.setOriginalName(originalFileName);
		attach.setLink(uploadDomain + uploadFileUrl);
		attach.setDomain(uploadDomain);
//		return R.status(this.localAttachService.save(attach));
		this.localAttachService.save(attach);

		return R.data(attach);
	}


	@ApiOperation(value = "获取当前登录用户名")
	@GetMapping(value = "getAccountName")
	public String getAccountName(HttpSession session) {
		UCService ucservice = UCCasServiceContext.getUcService();
		String loginName = ucservice.getCurrentLoginName(session);
		log.info("登录账号为： {}", loginName);
		return loginName;
	}

	@ApiLog("登录用户验证")
	@PostMapping("/ucLogin/token")
	@ApiOperation(value = "获取认证令牌", notes = "传入租户ID:tenantId,账号:account,密码:password")
	public Kv token(String token, HttpServletResponse response) throws Exception {

		if (!HttpUtil.validateToken(token)) {
			System.out.println("token失效");
		}

		EsmsUser userCache = (EsmsUser) CacheUtil.get("com:bladex:", "user:userInfo", token);
		if (userCache == null) {
			throw new Exception("token不存在");
		}
		User user = this.userService.getOne(new QueryWrapper<User>().eq("account", userCache.getAccount()));
		if (user == null) {
			user = new User();
			user.setAccount(userCache.getAccount());
			user.setPassword(DigestUtil.encrypt("123456"));
			user.setTenantId("000000");
			user.setUserType(1);
			user.setName(userCache.getName());
			user.setRealName(userCache.getName());
			user.setPhone(userCache.getBindPhone());
			user.setSex(userCache.getSex());
			user.setRoleId("1429601537717379074");
			user.setDeptId("1123598813738675201");
			user.setPostId("1123598817738675208");
			user.setStatus(1);
			this.userService.save(user);
			User newUser = this.userService.getOne(new QueryWrapper<User>().eq("account", userCache.getAccount()));
			UserDept userDept = new UserDept();
			userDept.setUserId(newUser.getId());
			userDept.setDeptId(1123598813738675201L);
			this.userDeptService.save(userDept);
		}

		String username = user.getAccount();
		String tenantId = user.getTenantId();
		String password = "10470c3b4b1fed12c3baac014be15fac67c6e815";
		Kv authInfo = Kv.create();

		//String grantType = WebUtil.getRequest().getParameter("grant_type");
		//System.out.println("grantType=="+grantType);
		String refreshToken = WebUtil.getRequest().getParameter("refresh_token");
		System.out.println("refreshToken==" + refreshToken);
		String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
		System.out.println("userType==" + userType);
		TokenParameter tokenParameter = new TokenParameter();
		tokenParameter.getArgs().set("tenantId", tenantId).set("username", username).set("password", password).set("grantType", "password").set("refreshToken", refreshToken).set("userType", userType);
		ITokenGranter granter = TokenGranterBuilder.getGranter("password");
		System.out.println("granter==" + granter);

		UserInfo userInfo = granter.grant(tokenParameter);
		System.out.println("userInfo===" + userInfo);
		if (userInfo == null || userInfo.getUser() == null) {
			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
		}

		if (Func.isEmpty(userInfo.getRoles())) {
			return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "未获得用户的角色信息");
		}
		Kv k = TokenUtil.createAuthInfo(userInfo);
		String access_token = k.getStr("access_token");
		System.out.println("access_token==" + access_token);
		String refresh_token = k.getStr("refresh_token");

		Cookie cookie1 = new Cookie("saber-access-token", access_token);
		cookie1.setMaxAge(365 * 24 * 60 * 60);
		cookie1.setPath("/");
//		Cookie cookie2 = new Cookie("saber-refresh_token", refresh_token);
//		cookie2.setMaxAge(365 * 24 * 60 * 60);
//		cookie2.setPath("/");
		response.addCookie(cookie1);
//		response.addCookie(cookie2);
		return k;
	}


	@ApiOperation(value = "验证token")
	@GetMapping(value = "validateToken")
	public R validateTokenController(String token) {
		try {
			boolean flag = HttpUtil.validateToken(token);
			if (flag) {
				return R.success("ok");
			} else {
				return R.fail("token失效。");
			}
		} catch (Exception e) {
			return R.fail("error");
		}
	}


	@ApiOperation(value = "测试用")
	@GetMapping(value = "testOne")
	public String validateTokenT(String token) {
		String url = "/v2/user/logout";
		try {
			String res = HttpUtil.postHandle(url, token);
			JSONObject jsonObject = JSONObject.parseObject(res);
			return res;
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}

	}


	@ApiOperation(value = "获取当前用户信息")
	@GetMapping(value = "getUserInfo")
	public R getUserInfo(String token) throws Exception {
		UCConstant ucConstant = UCCasServiceContext.getUcConstant();
		appSercert = ucConstant.getAppSecret();
		//验证token
		if (!HttpUtil.validateToken(token)) {
			CacheUtil.evict("com:bladex:", "user:userInfo", token);
			return R.fail("token已过期，请重新登陆。");
		}
		//获取缓存
		EsmsUser userCache = (EsmsUser) CacheUtil.get("com:bladex:", "user:userInfo", token);
		System.out.println("userCache==" + userCache);
		if (userCache != null) {
			return R.data(userCache);
		}
		//没有缓存请求远端数据
		UcLoginUserInfo userInfo = userHandle(HttpUtil.postHandle(userInfoUrl, token));
		if (StringUtil.isNullOrEmpty(userInfo.getAcType())) {
			throw new Exception("用户类型为空，请检查！");
		}
		if ("0".equals(userInfo.getAcType())) {
			if (null == userInfo.getPerUserVo()) {
				throw new Exception("个人信息为空，请检查！");
			}
			PerUserVo perUserVo = userInfo.getPerUserVo();
			String idNumber = perUserVo.getCredentNo();
			if (StringUtil.isNullOrEmpty(idNumber)) {
				return R.fail("该个人信息未录入到统一登陆平台，请处理！");
			}
			EsmsUser user = this.esmsUserService.getOne(new QueryWrapper<EsmsUser>().eq("user_id", perUserVo.getUserId()).eq("ac_type", 0));
			if (user == null) {
				user = new EsmsUser();
				user.setAccount(perUserVo.getAccount());
				user.setBindPhone(SignUtil.decryptAES(perUserVo.getBindPhone(), appSercert));
				user.setCertificationLevel(Integer.valueOf(perUserVo.getCertificationLevel()));
				user.setCertificationLevelName(perUserVo.getCertificationLevelName());
				user.setCredentNo(SignUtil.decryptAES(perUserVo.getCredentNo(), appSercert));
				user.setName(perUserVo.getName());
				user.setCredentType(Integer.valueOf(perUserVo.getCredentType()));
				user.setCredentTypeName(perUserVo.getCredentTypeName());
				user.setNation(perUserVo.getNation());
				user.setNationName(perUserVo.getNationName());
				user.setUserId(perUserVo.getUserId());
				user.setSex(Integer.valueOf(perUserVo.getSex()));
				user.setSexName(perUserVo.getSexName());
				user.setAcType(0);
				this.esmsUserService.save(user);
			}
			CacheUtil.put("com:bladex:", "user:userInfo", token, user);
			return R.data(user);
		}
		if ("1".equals(userInfo.getAcType())) {
			if (null == userInfo.getLegalUserVo()) {
				throw new Exception("法人信息为空，请检查！");
			}
			LegalUserVo legalUserVo = userInfo.getLegalUserVo();
			String uscCode = legalUserVo.getUscCode();
			if (StringUtil.isNullOrEmpty(uscCode)) {
				return R.fail("该法人信息未录入到统一登陆平台，请处理！");
			}
			EsmsUser enterpriseUser = this.esmsUserService.getOne(new QueryWrapper<EsmsUser>().eq("usc_code", uscCode).eq("ac_type", 1));
			if (enterpriseUser == null) {
				enterpriseUser = new EsmsUser();
				enterpriseUser.setAccount(legalUserVo.getAccount());
				enterpriseUser.setAddressDetail(legalUserVo.getAddressDetail());
				enterpriseUser.setBindPhone(SignUtil.decryptAES(legalUserVo.getBindPhone(), appSercert));
				enterpriseUser.setCertificationLevel(Integer.valueOf(legalUserVo.getCertificationLevel()));
				enterpriseUser.setCertificationLevelName(legalUserVo.getCertificationLevelName());
				enterpriseUser.setCredentNo(legalUserVo.getCredentNo());
				enterpriseUser.setCredentType(Integer.valueOf(legalUserVo.getCredentType()));
				enterpriseUser.setCredentTypeName(legalUserVo.getCredentTypeName());
				enterpriseUser.setEmail(legalUserVo.getEmail());
				enterpriseUser.setIdentityNo(SignUtil.decryptAES(legalUserVo.getIdentityNo(), appSercert));
				enterpriseUser.setIdentityType(Integer.valueOf(legalUserVo.getIdentityType()));
				enterpriseUser.setIdentityTypeName(legalUserVo.getIdentityTypeName());
				enterpriseUser.setLegUserId(legalUserVo.getLegUserId());
				enterpriseUser.setLegalUserAdress(legalUserVo.getLegalUserAdress());
				enterpriseUser.setName(legalUserVo.getName());
				enterpriseUser.setNation(legalUserVo.getNation());
				enterpriseUser.setNationName(legalUserVo.getNationName());
				enterpriseUser.setOrgName(legalUserVo.getOrgName());
				enterpriseUser.setOrgType(Integer.valueOf(legalUserVo.getOrgType()));
				enterpriseUser.setOrgTypeName(legalUserVo.getOrgTypeName());
				enterpriseUser.setSex(Integer.valueOf(legalUserVo.getSex()));
				enterpriseUser.setSexName(legalUserVo.getSexName());
				enterpriseUser.setTelephone(legalUserVo.getTelephone());
				enterpriseUser.setUscCode(legalUserVo.getUscCode());
				enterpriseUser.setAcType(1);
				this.esmsUserService.save(enterpriseUser);
				// 保存企业信息
				CompanyBasicInf companyBasicInf = new CompanyBasicInf();
				companyBasicInf.setUserId(enterpriseUser.getId());
				companyBasicInf.setUserName(enterpriseUser.getAccount());
				companyBasicInf.setCompanyName(enterpriseUser.getOrgName());
				companyBasicInf.setCreditCode(enterpriseUser.getUscCode());
				companyBasicInf.setCompanyType(enterpriseUser.getOrgTypeName());
				companyBasicInf.setLegalRepresentative(enterpriseUser.getName());
				companyBasicInf.setPhone(enterpriseUser.getBindPhone());
				companyBasicInf.setContactAddress(enterpriseUser.getAddressDetail());
				companyBasicInfService.save(companyBasicInf);
			}
			CacheUtil.put("com:bladex:", "user:userInfo", token, enterpriseUser);
			return R.data(enterpriseUser);
		}
		return R.success("ok");
	}


	@ApiOperation(value = "获取子账号信息")
	@GetMapping(value = "getSubAccount")
	public R getSubAccount(HttpSession session) throws Exception {
		UCService ucservice = UCCasServiceContext.getUcService();
		String token = ucservice.getCurrentToken(session);
		log.info("获取的token： {}", token);
		String userInfo = HttpUtil.postHandle(legalSubUrl, token);
		log.info("法人子账号信息为：{}", userInfo);
		return R.data(JSONObject.parseObject(userInfo));
	}


	private UcLoginUserInfo userHandle(String result) throws Exception {
		RestfulDto restfulDto = JSONObject.parseObject(result, RestfulDto.class);
		if (restfulDto.getCode().compareTo("400") < 0) {
			return restfulDto.getData();
		} else {
			throw new Exception("");
		}
	}

}
